package com.mac.sys.generator;

import com.google.common.base.CaseFormat;
import org.apache.commons.lang3.StringUtils;

import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Date;

/***
 *@Author:liangjilong
 *@Date:2015年12月5日下午12:25:12
 *@Email:jilongliang@sina.com
 *@Version:1.0
 *@CopyRight(c)Flong Intergrity Ltd.
 *@Desction:★★★★★★★★★★★★★★★代码生成器实现思路★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 *
 *   ★★在快速开发的过程中，为了节省时间和成本很多人都会开发自己的代码生成器，而且成为程序员开发过程中必不可少的神器.
 *   ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 *	  第一种：先有数据库表，然后通过jdbc链接数据库再读取表的字段等属性出来生成Entity,Dao,Service,Controller，JSP等代码
 *   这种必须是有数据库和表的思想,通过程序去读取数据库表的属性等信息,然后组织代码通过文件流生成文件.
 *
 *   ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 *   第二种：已经设计好数据库表文档，把所有表的字段属性配置到EXCEL或者CSV格式的文件通过JXL/POI技术去读取文件的字段实现
 *   Entity,Dao,Service,Controller，JSP,在过程中会借助Freemaker,Velocity去实现.三层和jsp，然后通过一下ORM(hibernate,
 *   ibatis,myibatis等)技术逆向生成数据库表.这种是无数据库表的思想. 在生成java的代码一般不建议建ORM映射主从表关系,通过
 *   SQL去建立关系,为啥？因为在一些大型的公司如：银行，阿里巴巴，电信等公司，很多项目开发过程中在数据库表很少建立表关系的
 *   因为在些业务复杂的情况下通过SQL和程序控制的解决方案比ORM映射关系方案占优势.比如优化性能/维护/灵活性更加好等.
 *   ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 *
 *   此程序可以再优化的，为了有些初学者,就不作太多的处理和优化.一些高手会编程更好的生成器，此程序只提供参考和学习,如有什么
 *   问题，可以多指出.共同学习和进步.谢谢！~
 *   ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 */
@SuppressWarnings("all")
public class CodeGenerator
{


    /*************************变量****Begin************************************/
    private static final String myEmail = "303417292@qq.com";//Email
    private static final String Version = "1.0";//版本
    private static final String Description = " ";//描述

    public static final String ENTER = "\n";//换行
    public static final String TAB = "\t";//tab
    public static final String TAB2 = "\t\t";
    public static final String TAB3 = "\t\t\t";
    public static final String TAB4 = "\t\t\t\t";
    public static final String TAB5 = "\t\t\t\t\t";
    public static final String TAB6 = "\t\t\t\t\t\t";
    public static final String TAB7 = "\t\t\t\t\t\t\t";
    public static final String TAB8 = "\t\t\t\t\t\t\t\t";
    public static final String TAB9 = "\t\t\t\t\t\t\t\t\t";
    public static final String NAME = "NAME";
    public static final String TABLE_CAT = "TABLE_CAT";//表 catalog
    public static final String TABLE_SCHEM = "TABLE_SCHEM";//表 schema
    public static final String TABLE_NAME = "TABLE_NAME";//表名
    public static final String TABLE_TYPE = "TABLE_TYPE";//表类型
    public static final String REMARKS = "REMARKS";//表注释
    public static final String TYPE = "TYPE";//表的类型
    public static final String SIZE = "SIZE";//大小
    public static final String CLASS = "CLASS";//类别

    /*************************变量****End************************************/

    public static final String NOW_DATE = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
    /***************获取数据库的配置连接************/
    public static final String JDBC_URL = PropertiesHelper.getValueByKey("jdbc.url");

    public static final String DB_NAME = PropertiesHelper.getValueByKey("jdbc.dbName");
    //从配置获取工程的报名路径
    public static final String ROOT_PACKAGE = PropertiesHelper.getValueByKey("rootPackage");
    //获取作者.
    public static final String AUTHOR = PropertiesHelper.getValueByKey("author");

    public static final String CODE_PATH = PropertiesHelper.getValueByKey("codePath");
    public static final String RESOURCE_PATH = PropertiesHelper.getValueByKey("resourcePath");

    //忽略表的后缀.
    public static final List<String> IGNORE_TABLE_PREFIX = new ArrayList<String>();



    /*******定义代码块*******/
    static
    {
        String ignoreTablePrefix = PropertiesHelper.getValueByKey("ignoreTablePrefix");
        if (ignoreTablePrefix.length() > 0)
        {
            String[] ignoreTablePrefixs = ignoreTablePrefix.split("\\s*\\,\\s*");
            for (String elem : ignoreTablePrefixs)
            {
                IGNORE_TABLE_PREFIX.add(elem);
            }
        }
    }


    /***
     * 生成实体类的代码
     * @param table
     * @throws Exception
     */
    public void createEntityClass(String table, String packageName) throws Exception
    {
        String tableConstantName = getTableConstantName(table);
        String className = getClassName(tableConstantName);
        List<Map<String, Object>> cols = this.getCols(table);

        StringBuilder sb = new StringBuilder();
        sb.append("package " + packageName + ".entity;");
        sb.append(ENTER);
        sb.append(ENTER);
        sb.append("import java.io.Serializable;").append(ENTER);
        sb.append("import com.baomidou.mybatisplus.annotations.TableName;").append(ENTER);
        sb.append("import com.baomidou.mybatisplus.annotations.TableId;").append(ENTER);
        sb.append("import com.baomidou.mybatisplus.enums.IdType;").append(ENTER);


        for (Map<String, Object> col : cols)
        {
            if (col.get(TYPE).toString().equalsIgnoreCase("DECIMAL"))
            {
                sb.append(ENTER);
                sb.append("import java.math.BigDecimal;");
                break;
            }
        }

        sb.append(ENTER);
        sb.append(ENTER);
        sb.append("/**\n * @Created：" + NOW_DATE + "\n * @Author " + AUTHOR + "\n");
        sb.append(" * @Version:").append(Version).append(ENTER);
        sb.append(" * @Description:").append(className).append(ENTER);
        sb.append(" * @Email:").append(myEmail).append("\n*/");
        sb.append(ENTER);
        sb.append("@TableName(\"" + table + "\")");
        sb.append(ENTER);
        sb.append("public class " + className + " implements Serializable");
        sb.append(ENTER);
        sb.append("{");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append("private static final long serialVersionUID = 1L;");

        sb.append(ENTER);
        sb.append(ENTER);


        for (Map<String, Object> col : cols)
        {
//            sb.append(TAB);
//            sb.append(ENTER);
//            if (col.get(NAME).toString().equalsIgnoreCase("ID"))
//            {
//                sb.append(TAB);
//                sb.append(ENTER);
//            }
            //id
            if("id".equals(col.get(NAME).toString()))
            {
                sb.append(ENTER);
                sb.append(TAB);
                sb.append("/**");
                sb.append(ENTER);
                sb.append(TAB);
                sb.append(" * 指定自增策略,  设置后，insert方法后，返回id");
                sb.append(ENTER);
                sb.append(TAB);
                sb.append(" */");
                sb.append(ENTER);
                sb.append(TAB);
                sb.append("@TableId(value = \"id\",type = IdType.AUTO)");
                sb.append(ENTER);
                sb.append(TAB);
                sb.append("private ");
                sb.append("Integer");
                String propertyName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, col.get(NAME).toString());
                sb.append(" " + propertyName + ";");
                sb.append(ENTER);
                continue;
            }


            sb.append(ENTER);
            sb.append(TAB);
            sb.append("/**");
            sb.append(ENTER);
            sb.append(TAB);
            sb.append(" * " +col.get(REMARKS).toString());
            sb.append(ENTER);
            sb.append(TAB);
            sb.append(" */");
            sb.append(ENTER);
            sb.append(TAB);
            sb.append("private ");
            if (col.get(NAME).toString().equalsIgnoreCase("ID") || col.get(NAME).toString().toUpperCase().endsWith("_ID"))
            {
                sb.append("Integer");
            } else if (Class.forName(col.get(CLASS).toString()).isAssignableFrom(Date.class) ||
                    Class.forName(col.get(CLASS).toString()) == Timestamp.class)
            {
                sb.append("Date");
            } else if (getClassName(col.get(NAME).toString()).equals(Class.forName(col.get(CLASS).toString()).getSimpleName()))
            {
                sb.append(col.get(CLASS));
            } else
            {
                sb.append(Class.forName(col.get(CLASS).toString()).getSimpleName());
            }
            //sb.append(" " + getFieldName(col.get(NAME).toString()) + ";");
//            String propertyName = StringUtils.uncapitalize();
            String propertyName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, col.get(NAME).toString());
            sb.append(" " + propertyName + ";");
            sb.append(ENTER);
        }
        sb.append(ENTER);
        for (Map<String, Object> col : cols)
        {
            sb.append(TAB);
            sb.append("public ");
            if (col.get(NAME).toString().equalsIgnoreCase("ID") || col.get(NAME).toString().toUpperCase().endsWith("_ID"))
            {
                sb.append("Integer");
            } else if (Class.forName(col.get(CLASS).toString()).isAssignableFrom(Date.class) ||
                    Class.forName(col.get(CLASS).toString()) == Timestamp.class)
            {
                sb.append("Date");
            } else if (getClassName(col.get(NAME).toString()).equals(Class.forName(col.get(CLASS).toString()).getSimpleName()))
            {
                sb.append(col.get(CLASS));
            } else
            {
                sb.append(Class.forName(col.get(CLASS).toString()).getSimpleName());
            }
            String propertyName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, col.get(NAME).toString());
            sb.append(" ").append("get").append(propertyName.replaceFirst("\\b(\\w)|\\s(\\w)", propertyName.substring(0, 1).toUpperCase()));
            sb.append("()");
            sb.append(ENTER);
            sb.append(TAB);
            sb.append("{");
            sb.append(ENTER);
            sb.append(TAB);
            sb.append(TAB);
            sb.append("return ").append(propertyName).append(";");
            sb.append(ENTER);
            sb.append(TAB);
            sb.append("}");
            sb.append(ENTER);
            sb.append(TAB);
            sb.append("public void ").append("set").append(propertyName.replaceFirst("\\b(\\w)|\\s(\\w)", propertyName.substring(0, 1).toUpperCase()));
            sb.append("(");
            if (propertyName.equalsIgnoreCase("ID") || propertyName.toUpperCase().endsWith("_ID"))
            {
                sb.append("Integer");
            } else if (Class.forName(col.get(CLASS).toString()).isAssignableFrom(Date.class) ||
                    Class.forName(col.get(CLASS).toString()) == Timestamp.class)
            {
                sb.append("Date");
            } else if (getClassName(propertyName).equals(Class.forName(col.get(CLASS).toString()).getSimpleName()))
            {
                sb.append(col.get(CLASS));
            } else
            {
                sb.append(Class.forName(col.get(CLASS).toString()).getSimpleName());
            }
            sb.append(" ").append(propertyName);
            sb.append(")");
            sb.append(ENTER);
            sb.append(TAB);
            sb.append("{");
            sb.append(ENTER);
            sb.append(TAB);
            sb.append(TAB);
            sb.append("this.").append(propertyName).append(" = ").append(propertyName).append(";");
            sb.append(ENTER);
            sb.append(TAB);
            sb.append("}");
            sb.append(ENTER);
        }

        sb.append(TAB);
        sb.append("public String toString()");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append("{");
        sb.append(ENTER);
        sb.append(TAB2);
        sb.append("return ");
        for (Map<String, Object> col : cols)
        {
            String propertyName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, col.get(NAME).toString());
            sb.append("\"");
            sb.append(propertyName);
            sb.append(":\" + ");
            sb.append(propertyName);
            sb.append("+\"\t\"+");
        }
        sb.append("\"\"");
        sb.append(";");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append("}");
        sb.append(ENTER);




        sb.append("}");
        sb.append(ENTER);
        FileUtils.save(CODE_PATH + packageName.replaceAll("\\.", "/") + "/entity/" + className + ".java", sb.toString());
    }

    /***
     * 生成sql配置文件
     * @param table
     * @throws Exception
     */
    public void createMappingXmlClass(String table, String packageName) throws Exception
    {
        String className = getClassName(getTableConstantName(table));
        String objectName = StringUtils.uncapitalize(className);
        List<Map<String, Object>> cols = this.getCols(table);

        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>").append(ENTER);
        sb.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">").append(ENTER);
        sb.append("<mapper namespace=\""+packageName + ".dao."+className+"Dao"+"\">").append(ENTER).append(ENTER);

        sb.append(TAB);
        sb.append("<select id=\"findList\" resultType=\"map\" parameterType=\"map\">").append(ENTER);
        sb.append(TAB2);
        sb.append("select ");
        for (int i=0; i<cols.size(); i++)
        {
            Map<String, Object> col = cols.get(i);
            String propertyName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, col.get(NAME).toString());

            if(i%5==0)
            {
                sb.append(ENTER);
                sb.append(TAB3);
            }

            if(i == cols.size()-1)
            {
                sb.append(col.get(NAME).toString()+" " + propertyName).append(ENTER);
                break;
            }
            sb.append(col.get(NAME).toString()+" " + propertyName + ",");
        }

        sb.append(TAB2).append("from " + table).append(ENTER);

        sb.append(TAB2).append("<where>").append(ENTER);
        sb.append(TAB3).append("<if test=\"id != null and id != '' and id !=0\">").append(ENTER);
        sb.append(TAB4).append("and id=#{id}").append(ENTER);
        sb.append(TAB3).append("</if>").append(ENTER);
        sb.append(TAB2).append("</where>").append(ENTER);
        sb.append(TAB).append("</select>").append(ENTER).append(ENTER);

        sb.append("</mapper>").append(ENTER);
        FileUtils.save(RESOURCE_PATH  + "/mapping/" + className + "-mapping.xml", sb.toString());
    }
    /***
     * 生成dao接口interface类的代码
     * @param table
     * @throws Exception
     */
    public void createDaoClass(String table, String packageName) throws Exception
    {
        String className = getClassName(getTableConstantName(table));
        String objectName = StringUtils.uncapitalize(className);

        StringBuilder sb = new StringBuilder();
        sb.append("package " + packageName + ".dao;").append(ENTER).append(ENTER);
        sb.append("import java.util.List;").append(ENTER);
        sb.append("import java.util.Map;").append(ENTER);
        sb.append("import ").append(packageName).append(".entity.").append(className).append(";").append(ENTER);
        sb.append("import com.baomidou.mybatisplus.plugins.Page;").append(ENTER);
        sb.append("import com.baomidou.mybatisplus.mapper.BaseMapper;").append(ENTER);

        sb.append(ENTER);
        sb.append(ENTER);
        sb.append("/**\n * @Created：" + NOW_DATE + "\n * @Author " + AUTHOR + "\n");
        sb.append(" * @Version:").append(Version).append(ENTER);
        sb.append(" * @Description:").append(className).append(ENTER);
        sb.append(" * @Email:").append(myEmail).append("\n*/");
        sb.append(ENTER);

        sb.append("public interface " + className + "Dao extends BaseMapper<" + className + ">").append(ENTER);
        sb.append("{").append(ENTER);
        sb.append(TAB);
        sb.append("public List<Map<String, Object>> findList(Page page, Map<String, Object> params);").append(ENTER);

        sb.append(ENTER);
        sb.append("}");
        sb.append(ENTER);
        FileUtils.save(CODE_PATH + packageName.replaceAll("\\.", "/") + "/dao/" + className + "Dao.java", sb.toString());
    }

    /***
     * 生成dao的实现类的代码
     * @param table
     * @throws Exception
     */
    public void createDaoImplClass(String table, String packageName) throws Exception
    {
        String className = getClassName(getTableConstantName(table));
        String objectName = StringUtils.uncapitalize(className);
        String tableName = StringUtils.lowerCase(getTableConstantName(table));//获取表名

        StringBuilder sb = new StringBuilder();
        sb.append("package " + packageName + ".dao.impl;").append(ENTER);
        sb.append("import java.io.Serializable;").append(ENTER);
        sb.append("import org.apache.commons.lang3.StringUtils;").append(ENTER);
        sb.append("import org.springframework.stereotype.Repository;").append(ENTER);
        sb.append("import com.flong.commons.persistence.bean.SimplePage;").append(ENTER);
        sb.append("import com.flong.commons.persistence.dao.impl.EntityDaoSupport;").append(ENTER);
        sb.append("import com.flong.modules.dao." + className + "Dao;").append(ENTER);
        sb.append("import com.flong.modules.pojo." + className + ";").append(ENTER);


        sb.append(ENTER);
        sb.append(ENTER);
        sb.append("/**\n * @Created：" + NOW_DATE + "\n * @Author " + AUTHOR + "\n");
        sb.append(" * @Version:").append(Version).append(ENTER);
        sb.append(" * @Description:").append(className).append(ENTER);
        sb.append(" * @Email:").append(myEmail).append("\n*/");
        sb.append(ENTER);
        sb.append("@Repository");//这个是spring的注解
        sb.append(ENTER);
        sb.append("public class " + className + "DaoImpl extends EntityDaoSupport<" + className + "> implements " + className + "Dao {");


        sb.append("/**查询*/").append(ENTER);
        sb.append(" public List<" + className + "> list(SimplePage simplePage," + className + " " + objectName + "){").append(ENTER);

        sb.append(ENTER);

        String mergeField = "";//合并字段.

        //--遍历获取列,并拼接字符串,SQL的查询列,查询不建议用*去查询表的所有列.
        for (Map<String, Object> col : getCols(table))
        {

            //
            if (col.get(NAME).toString() != null)
            {
                mergeField += col.get(NAME).toString() + ",";//合并字段并用,隔开字段名
            }
        }
        //去掉最后一个,号然后拼接成一个完成的select查询字段
        if (mergeField != null)
        {
            mergeField = mergeField.substring(0, mergeField.length() - 1);
        }

        sb.append("    String sql = ").append("\" select " + mergeField + " from ").append(tableName).append(" where 1=1 \" ").append(ENTER);//这个TABLE是实体类的变量
        //daoQuery这个是底层封装的一个接口,自个可以更加自己需求封装.
        sb.append("    List<" + className + "> list= daoQuery.query(sql," + className + ".class,simplePage);").append(ENTER);
        sb.append(" return list;").append(ENTER);

        sb.append("}").append(ENTER);//查询的结束{


        sb.append("/**保存数据*/").append(ENTER);
        sb.append(" public void saveData(" + className + " " + objectName + "){").append(ENTER);
        sb.append("   try {").append(ENTER);
        sb.append("	     saveOrUpdate(" + className + ");").append(ENTER);
        sb.append("   } catch (DaoAccessException e) {").append(ENTER);
        sb.append("      e.printStackTrace();").append(ENTER);
        sb.append("  }").append(ENTER);

        sb.append("}");


        sb.append("/**更新数据*/").append(ENTER);

        sb.append(" public void updateData(" + className + " " + objectName + "){").append(ENTER);

        sb.append("   try {").append(ENTER);
        sb.append("	     saveOrUpdate(" + className + ");").append(ENTER);
        sb.append("   } catch (DaoAccessException e) {").append(ENTER);
        sb.append("      e.printStackTrace();").append(ENTER);
        sb.append("  }").append(ENTER);

        sb.append("}");


        sb.append("/**删除数据*/").append(ENTER);
        sb.append(" public void deleteData(Long pk){").append(ENTER);

        sb.append("   try {").append(ENTER);
        sb.append("	     delete(pk);").append(ENTER);
        sb.append("   } catch (DaoAccessException e) {").append(ENTER);
        sb.append("      e.printStackTrace();").append(ENTER);
        sb.append("  }").append(ENTER);


        sb.append("}");

        sb.append(ENTER);
        sb.append(ENTER);
        sb.append("}");
        sb.append(ENTER);
        FileUtils.save(CODE_PATH + packageName.replaceAll("\\.", "/") + "/dao/impl/" + className + "DaoImpl.java", sb.toString());
    }


    /***
     * 创建Service的接口
     * createServiceClass
     * @param table
     */
    public void createServiceClass(String table, String packageName)
    {

        String className = getClassName(getTableConstantName(table));
        String objectName = StringUtils.uncapitalize(className);

        StringBuilder sb = new StringBuilder();

        sb.append("package " + packageName + ".service;").append(ENTER);


        sb.append("import java.util.List;").append(ENTER);
        sb.append("import java.util.Map;").append(ENTER);
        sb.append("import com.baomidou.mybatisplus.plugins.Page;").append(ENTER);
        sb.append("import ").append(packageName).append(".entity.").append(className).append(";").append(ENTER);
        sb.append("import com.baomidou.mybatisplus.service.IService;").append(ENTER);


        sb.append(ENTER);
        sb.append(ENTER);
        sb.append("/**\n * @Created：" + NOW_DATE + "\n * @Author " + AUTHOR + "\n");
        sb.append(" * @Version:").append(Version).append(ENTER);
        sb.append(" * @Description:").append(className).append(ENTER);
        sb.append(" * @Email:").append(myEmail).append("\n*/");
        sb.append(ENTER);
        sb.append("public interface " + className + "Service extends IService<" + className + ">").append(ENTER);
        sb.append("{").append(ENTER);

        sb.append(TAB);
        sb.append("public List<Map<String, Object>> findList(Page page, Map<String, Object> params);");

        sb.append(ENTER);
        sb.append(ENTER);
        sb.append("}");
        sb.append(ENTER);
        FileUtils.save(CODE_PATH + packageName.replaceAll("\\.", "/") + "/service/" + className + "Service.java", sb.toString());

    }

    /***
     * 创建Service层的实现类
     * createServiceImplClass
     * @param table
     */
    public void createServiceImplClass(String table, String packageName)
    {

        String className = getClassName(getTableConstantName(table));

        String objectName = StringUtils.uncapitalize(className);

        StringBuilder sb = new StringBuilder();

        sb.append("package " + packageName + ".service.impl;").append(ENTER);
        sb.append("import java.util.List;").append(ENTER);
        sb.append("import java.util.Map;").append(ENTER);
        sb.append("import com.baomidou.mybatisplus.plugins.Page;").append(ENTER);
        sb.append("import org.springframework.beans.factory.annotation.Autowired;").append(ENTER);
        sb.append("import com.baomidou.mybatisplus.service.impl.ServiceImpl;").append(ENTER);
        sb.append("import org.springframework.stereotype.Service;").append(ENTER);


        sb.append("import " + packageName + ".dao." + className + "Dao;").append(ENTER);
        sb.append("import " + packageName + ".service." + className + "Service;").append(ENTER);
        sb.append("import " + packageName + ".entity." + className + ";").append(ENTER);


        sb.append(ENTER);
        sb.append(ENTER);
        sb.append("/**\n * @Created：" + NOW_DATE + "\n * @Author " + AUTHOR + "\n");
        sb.append(" * @Version:").append(Version).append(ENTER);
        sb.append(" * @Description:").append(className).append(ENTER);
        sb.append(" * @Email:").append(myEmail).append("\n*/");
        sb.append(ENTER);
        sb.append("@Service");
        sb.append(ENTER);
        sb.append("public class " + className + "ServiceImpl extends ServiceImpl<"+className+"Dao, "+className+"> implements " + className + "Service").append(ENTER);
        sb.append("{");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append("@Autowired ");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(className + "Dao " + objectName + "Dao;");






        sb.append(ENTER);
        sb.append(ENTER);

        sb.append(TAB);
        sb.append("public List<Map<String, Object>> findList(Page page, Map<String, Object> params)").append(ENTER);
        sb.append(TAB);
        sb.append("{").append(ENTER);
        sb.append(TAB2);
        sb.append("return "+objectName+"Dao.findList(page, params);").append(ENTER);
        sb.append(TAB);
        sb.append("}").append(ENTER).append(ENTER);
        sb.append("}");
        sb.append(ENTER);
        FileUtils.save(CODE_PATH + packageName.replaceAll("\\.", "/") + "/service/impl/" + className + "ServiceImpl.java", sb.toString());

    }


    /***
     * 创建控制层类Controller
     * @param table
     */
    public void createControllerClass(String table, String packageName)
    {
        //类名
        String className = getClassName(getTableConstantName(table));
        //通过 org.apache.commons.lang3.StringUtils的uncapitalize方法把类名第一个字母转换成小写
        String objectName = StringUtils.uncapitalize(className);

        //通过 org.apache.commons.lang3.StringUtils的lowerCase方法把类名整个单词转化成小写然后为springmvc的路径返回jsp请求.
        String[] pakgs = packageName.split("\\.");

        String BASE_PATH = "/" + pakgs[pakgs.length - 1] + "/" + objectName + "/";//modules+模块名

        StringBuilder sb = new StringBuilder();
        sb.append("package " + packageName + ".controller;").append(ENTER);
        /*******处理这个导入需要的类*********/
        sb.append("import java.util.List;").append(ENTER);
        sb.append("import javax.servlet.http.HttpServletRequest;").append(ENTER);
        sb.append("import javax.servlet.http.HttpServletResponse;").append(ENTER);
        sb.append("import org.springframework.beans.factory.annotation.Autowired;").append(ENTER);
        sb.append("import org.springframework.stereotype.Controller;").append(ENTER);
        sb.append("import org.springframework.web.bind.annotation.RequestMapping;").append(ENTER);
        sb.append("import org.springframework.web.bind.annotation.ResponseBody;").append(ENTER);
        sb.append("import java.util.Map;").append(ENTER);
        sb.append("import java.util.HashMap;").append(ENTER);
        sb.append("import com.baomidou.mybatisplus.plugins.Page;").append(ENTER);


        sb.append("import " + packageName + ".service." + className + "Service;").append(ENTER);
        sb.append("import " + packageName + ".entity." + className + ";").append(ENTER);


        sb.append(ENTER);
        sb.append(ENTER);
        sb.append("/**\n * @Created：" + NOW_DATE + "\n * @Author " + AUTHOR + "\n");
        sb.append(" * @Version:").append(Version).append(ENTER);
        sb.append(" * @Description:").append(className).append(ENTER);
        sb.append(" * @Email:").append(myEmail).append("\n*/");
        sb.append(ENTER);
        sb.append(ENTER);
        sb.append("@Controller").append(ENTER);
        sb.append("@RequestMapping(\"/" + objectName + "\")").append(ENTER);
        sb.append("public class " + className + "Controller").append(ENTER);
        sb.append("{");
        sb.append(ENTER);
        sb.append(ENTER);
        sb.append("    @Autowired ").append(ENTER);
        sb.append(TAB);
        sb.append( className + "Service " + objectName + "Service;");//注入Service层的接口Name
        sb.append(ENTER);

        //创建一个默认的查询..
        sb.append(ENTER);
        sb.append(TAB);
        sb.append("@RequestMapping(value=\"/listPage\")").append(ENTER);
        sb.append(TAB);
        sb.append("public Object listPage(HttpServletRequest request ,HttpServletResponse response)").append(ENTER);
        sb.append(TAB);
        sb.append("{");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("return \"" + BASE_PATH + "list\";");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append("}");
        sb.append(ENTER).append(ENTER);

        sb.append(TAB).append("/**").append(ENTER);
        sb.append(TAB).append(" * @param pageNum  第几页").append(ENTER);
        sb.append(TAB).append(" * @param orderField 排序字段").append(ENTER);
        sb.append(TAB).append(" * @param ascStr  顺序还是倒序").append(ENTER);
        sb.append(TAB).append(" * @return page 插件mysqlplus 封装的分页对象").append(ENTER);
        sb.append(TAB).append(" */").append(ENTER);
        sb.append(TAB);
        sb.append("@ResponseBody").append(ENTER);
        sb.append(TAB);
        sb.append("@RequestMapping(value=\"/list\")").append(ENTER);
        sb.append(TAB);
        sb.append("public Object list(HttpServletRequest request ,HttpServletResponse response,").append(ENTER);
        sb.append(TAB6);
        sb.append("Integer pageNum, Integer pageSize, String orderField, String ascStr, Integer id)").append(ENTER);

        sb.append(TAB);
        sb.append("{");
        sb.append(ENTER);
        sb.append(TAB2).append("Map<String, Object> params = new HashMap<String, Object>();").append(ENTER);
        sb.append(TAB2).append("params.put(\"id\", id);").append(ENTER);
        sb.append(TAB2).append("pageNum = pageNum + 1; //前端从0开始").append(ENTER);
        sb.append(TAB2).append("Page page = new Page(pageNum, pageSize);").append(ENTER);

        sb.append(TAB2).append("page.setOrderByField(orderField);").append(ENTER);
        sb.append(TAB2).append("if(\"desc\".equals(ascStr))").append(ENTER);
        sb.append(TAB2).append("{").append(ENTER);
        sb.append(TAB3).append("page.setAsc(false);").append(ENTER);
        sb.append(TAB2).append("}").append(ENTER);
        sb.append(TAB2).append("page.setRecords("+ objectName+"Service.findList(page, params));").append(ENTER);


        sb.append(ENTER);
        sb.append(TAB2).append("return page;").append(ENTER);
        sb.append(TAB);
        sb.append("}");
        sb.append(ENTER);


        sb.append(ENTER);
        sb.append(TAB);
        sb.append("@RequestMapping(value=\"/addPage\")").append(ENTER);
        sb.append(TAB);
        sb.append("public Object addPage(HttpServletRequest request ,HttpServletResponse response)").append(ENTER);
        sb.append(TAB);
        sb.append("{");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("return \"" + BASE_PATH + "add\";");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append("}");
        sb.append(ENTER).append(ENTER);

        sb.append(TAB);
        sb.append("@ResponseBody").append(ENTER);
        sb.append(TAB);
        sb.append("@RequestMapping(value=\"/add\")").append(ENTER);
        sb.append(TAB);
        sb.append("public Object add(HttpServletRequest request ,HttpServletResponse response, "+className+" "+objectName+")").append(ENTER);
        sb.append(TAB);
        sb.append("{");
        sb.append(ENTER);
        sb.append(TAB2);
        sb.append(objectName + ".setId(new Integer(0));");

        sb.append(ENTER);
        sb.append(TAB2);
        sb.append(objectName + "Service.insert("+objectName+");");
        sb.append(ENTER);
        sb.append(TAB2);
        sb.append("Map<String, Object> map = new HashMap<String, Object>();");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("map.put(\"resCode\", " + "\"1\");");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("map.put(\"resMsg\", " + "\"新增成功\");");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("return map;");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append("}");
        sb.append(ENTER);

        sb.append(ENTER);
        sb.append(TAB);
        sb.append("@RequestMapping(value=\"/editPage\")").append(ENTER);
        sb.append(TAB);
        sb.append("public Object editPage(HttpServletRequest request ,HttpServletResponse response, Integer id)").append(ENTER);
        sb.append(TAB);
        sb.append("{").append(ENTER);
        sb.append(TAB2);
        sb.append(className+" "+objectName+" = "+objectName+"Service.selectById(id);").append(ENTER);
        sb.append(TAB2);
        sb.append("request.setAttribute(\""+objectName+"\", "+objectName+");").append(ENTER);
        sb.append(TAB2);
        sb.append("return \"" + BASE_PATH + "edit\";").append(ENTER);
        sb.append(TAB);
        sb.append("}");
        sb.append(ENTER).append(ENTER);

        sb.append(TAB);
        sb.append("@ResponseBody").append(ENTER);
        sb.append(TAB);
        sb.append("@RequestMapping(value=\"/edit\")").append(ENTER);
        sb.append(TAB);
        sb.append("public Object edit(HttpServletRequest request ,HttpServletResponse response, "+className+" "+objectName+")").append(ENTER);
        sb.append(TAB);
        sb.append("{");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append(objectName + "Service.updateById("+objectName+");");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("Map<String, Object> map = new HashMap<String, Object>();");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("map.put(\"resCode\", " + "\"1\");");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("map.put(\"resMsg\", " + "\"修改成功\");");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("return map;");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append("}");
        sb.append(ENTER).append(ENTER);

        sb.append(TAB);
        sb.append("@ResponseBody").append(ENTER);
        sb.append(TAB);
        sb.append("@RequestMapping(value=\"/delete\")").append(ENTER);
        sb.append(TAB);
        sb.append("public Object delete(HttpServletRequest request ,HttpServletResponse response, Integer id)").append(ENTER);
        sb.append(TAB);
        sb.append("{");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append(objectName + "Service.deleteById(id);");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("Map<String, Object> map = new HashMap<String, Object>();");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("map.put(\"resCode\", " + "\"1\");");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("map.put(\"resMsg\", " + "\"删除成功\");");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append(TAB);
        sb.append("return map;");
        sb.append(ENTER);
        sb.append(TAB);
        sb.append("}");
        sb.append(ENTER);

        sb.append("}");
        sb.append(ENTER);


        FileUtils.save(CODE_PATH + packageName.replaceAll("\\.", "/") + "/controller/" + className + "Controller.java", sb.toString());
    }


    /***
     * 创建JSP页面.
     * 以bootstrap3.x为主.
     * @param table
     */
    public void createHtmlView(String table, String packageName) throws Exception
    {
        this.createPageList(table, packageName);
        this.createPageAdd(table, packageName);
        this.createPageEdit(table, packageName);
    }

    public void createPageEdit(String table, String packageName) throws Exception
    {
        String tableConstantName = getTableConstantName(table);

        String className = getClassName(tableConstantName);//获取类名
        //通过 org.apache.commons.lang3.StringUtils的uncapitalize方法把类名第一个字母转换成小写
        String objectName = StringUtils.uncapitalize(className);
        List<Map<String, Object>> cols = this.getCols(table);

        StringBuilder sb = new StringBuilder();

        sb.append("<% layout('/views/layouts/default.html', {title: '"+className+"-编辑', libs: ['validate']}){ %>").append(ENTER);
        sb.append("<div class=\"content-wrapper\">").append(ENTER);
        sb.append(TAB);
        sb.append("<section class=\"content-header\">").append(ENTER);
        sb.append(TAB2);
        sb.append("<h1>" +className+ "<small>编辑</small></h1>").append(ENTER);
        sb.append(TAB);
        sb.append("</section>").append(ENTER).append(ENTER);

        sb.append(TAB);
        sb.append("<section class=\"content\">").append(ENTER);
        sb.append(TAB2);
        sb.append("<div class=\"row\">").append(ENTER);
        sb.append(TAB3);
        sb.append("<div class=\"col-md-6\">").append(ENTER);
        sb.append(TAB4);
        sb.append("<div class=\"box box-primary\">").append(ENTER);
        sb.append(TAB5);
        sb.append("<div class=\"box-header with-border\">").append(ENTER);
        sb.append(TAB6);
        sb.append("<!--<h3 class=\"box-title\">Quick Example</h3>-->").append(ENTER);
        sb.append(TAB5);
        sb.append("</div>").append(ENTER);
        sb.append(TAB5);
        sb.append("<form id=\"myForm\" role=\"form\" action=\"/" + objectName + "/edit\">").append(ENTER);
        sb.append(TAB6);
        sb.append("<div class=\"box-body\">").append(ENTER);



        for(Map<String, Object> col : cols)
        {
            String remarksDBName = col.get(REMARKS).toString();
            String remarks = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, remarksDBName);


            String propertyDBName = col.get(NAME).toString();
            String propertyName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, propertyDBName);


            if("id".equals(propertyName))
            {
                sb.append(TAB7);
                sb.append("<input type=\"hidden\" name=\""+propertyName+"\" class=\"form-control\" id=\""+propertyName+"\" placeholder=\"Enter "+propertyName+"\" value=\"${"+objectName+"."+propertyName+"}\">").append(ENTER);
                continue;
            }
            sb.append(TAB7);
            sb.append("<div class=\"form-group\">").append(ENTER);
            sb.append(TAB8);
            sb.append("<label>"+remarks+"</label>").append(ENTER);
            sb.append(TAB8);
            sb.append("<input type=\"text\" name=\""+propertyName+"\" class=\"form-control\" id=\""+propertyName+"\" placeholder=\"Enter "+propertyName+"\" value=\"${"+objectName+"."+propertyName+"}\">").append(ENTER);
            sb.append(TAB7);
            sb.append("</div>").append(ENTER);
        }

        sb.append(TAB6);
        sb.append("</div>").append(ENTER).append(ENTER);
        sb.append(TAB6);
        sb.append("<div class=\"box-footer\">").append(ENTER);
        sb.append(TAB7);
        sb.append(" <button id=\"myButton\" type=\"button\" class=\"btn btn-primary\">Submit - 提交</button>&nbsp;&nbsp;").append(ENTER);
        sb.append(TAB7);
        sb.append("<a href=\"/" + objectName + "/listPage\"><button id=\"backButton\" type=\"button\" class=\"btn btn-default\">返 回</button></a>").append(ENTER).append(ENTER);
        sb.append(TAB7);
        sb.append("<div id=\"msgDiv\" style=\"float:right;margin-top:7px;color:red;\"></div>").append(ENTER);
        sb.append(TAB6);
        sb.append("</div>").append(ENTER);
        sb.append(TAB5);
        sb.append("</form>").append(ENTER);
        sb.append(TAB4);
        sb.append("</div>").append(ENTER);
        sb.append(TAB3);
        sb.append("</div>").append(ENTER);
        sb.append(TAB2);
        sb.append("</div>").append(ENTER);
        sb.append(TAB);
        sb.append("</section>").append(ENTER);
        sb.append("</div>").append(ENTER).append(ENTER);

        sb.append("<% } %>").append(ENTER);
        sb.append("<script>").append(ENTER);
        sb.append(TAB);
        sb.append("$(\"#myButton\").click(function(){").append(ENTER);
        sb.append(TAB2);
        sb.append("$(\"#myForm\").ajaxSubmit({").append(ENTER);
        sb.append(TAB3);
        sb.append("success: function (data) {").append(ENTER);
        sb.append(TAB4);
        sb.append("if (data.resCode == 1 || data.resCode == 2){").append(ENTER);
        sb.append(TAB5);
        sb.append("$(\"#msgDiv\").text(data.resMsg);").append(ENTER);
        sb.append(TAB4);
        sb.append("}").append(ENTER);
        sb.append(TAB3);
        sb.append("},").append(ENTER);
        sb.append(TAB3);
        sb.append("error: function () {").append(ENTER);
        sb.append(TAB4);
        sb.append("$(\"#msgDiv\").text(\"系统出现错误，请联系管理员\");").append(ENTER);
        sb.append(TAB3);
        sb.append("}").append(ENTER);
        sb.append(TAB2);
        sb.append("});").append(ENTER);
        sb.append(TAB);
        sb.append("});").append(ENTER);
        sb.append("document.body.style.backgroundColor = '#ECF0F5';").append(ENTER);
        sb.append("</script>").append(ENTER);


        String companyArr[] = packageName.split("\\.");
        int len = companyArr.length;
        String company = companyArr[len-1];
        String path = RESOURCE_PATH + "views\\" + company +"\\"+ objectName + "\\edit.html";
        FileUtils.save(path, sb.toString());
    }

    public void createPageAdd(String table, String packageName) throws Exception
    {
        String tableConstantName = getTableConstantName(table);

        String className = getClassName(tableConstantName);//获取类名
        //通过 org.apache.commons.lang3.StringUtils的uncapitalize方法把类名第一个字母转换成小写
        String objectName = StringUtils.uncapitalize(className);
        List<Map<String, Object>> cols = this.getCols(table);

        StringBuilder sb = new StringBuilder();

        sb.append("<% layout('/views/layouts/default.html', {title: '"+className+"-新增', libs: ['validate']}){ %>").append(ENTER);
        sb.append("<div class=\"content-wrapper\">").append(ENTER);
        sb.append(TAB);
        sb.append("<section class=\"content-header\">").append(ENTER);
        sb.append(TAB2);
        sb.append("<h1>" +className+ "<small>新增</small></h1>").append(ENTER);
        sb.append(TAB);
        sb.append("</section>").append(ENTER).append(ENTER);

        sb.append(TAB);
        sb.append("<section class=\"content\">").append(ENTER);
        sb.append(TAB2);
        sb.append("<div class=\"row\">").append(ENTER);
        sb.append(TAB3);
        sb.append("<div class=\"col-md-6\">").append(ENTER);
        sb.append(TAB4);
        sb.append("<div class=\"box box-primary\">").append(ENTER);
        sb.append(TAB5);
        sb.append("<div class=\"box-header with-border\">").append(ENTER);
        sb.append(TAB6);
        sb.append("<!--<h3 class=\"box-title\">Quick Example</h3>-->").append(ENTER);
        sb.append(TAB5);
        sb.append("</div>").append(ENTER);
        sb.append(TAB5);
        sb.append("<form id=\"myForm\" role=\"form\" action=\"/" + objectName + "/add\">").append(ENTER);
        sb.append(TAB6);
        sb.append("<div class=\"box-body\">").append(ENTER);



        for(Map<String, Object> col : cols)
        {
            String remarksDBName = col.get(REMARKS).toString();
            String remarks = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, remarksDBName);

            String propertyDBName = col.get(NAME).toString();
            String propertyName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, propertyDBName);


            if("id".equals(propertyName))
            {
                continue;
            }
            sb.append(TAB7);
            sb.append("<div class=\"form-group\">").append(ENTER);
            sb.append(TAB8);
            sb.append("<label>"+remarks+"</label>").append(ENTER);
            sb.append(TAB8);
            sb.append("<input type=\"text\" name=\""+propertyName+"\" class=\"form-control\" id=\""+propertyName+"\" placeholder=\"Enter "+propertyName+"\">").append(ENTER);
            sb.append(TAB7);
            sb.append("</div>").append(ENTER);
        }

        sb.append(TAB6);
        sb.append("</div>").append(ENTER).append(ENTER);
        sb.append(TAB6);
        sb.append("<div class=\"box-footer\">").append(ENTER);
        sb.append(TAB7);
        sb.append(" <button id=\"myButton\" type=\"button\" class=\"btn btn-primary\">Submit - 提交</button>&nbsp;&nbsp;").append(ENTER);
        sb.append(TAB7);
        sb.append("<a href=\"/" + objectName + "/listPage\"><button id=\"backButton\" type=\"button\" class=\"btn btn-default\">返 回</button></a>").append(ENTER).append(ENTER);
        sb.append(TAB7);
        sb.append("<div id=\"msgDiv\" style=\"float:right;margin-top:7px;color:red;\"></div>").append(ENTER);
        sb.append(TAB6);
        sb.append("</div>").append(ENTER);
        sb.append(TAB5);
        sb.append("</form>").append(ENTER);
        sb.append(TAB4);
        sb.append("</div>").append(ENTER);
        sb.append(TAB3);
        sb.append("</div>").append(ENTER);
        sb.append(TAB2);
        sb.append("</div>").append(ENTER);
        sb.append(TAB);
        sb.append("</section>").append(ENTER);
        sb.append("</div>").append(ENTER).append(ENTER);

        sb.append("<% } %>").append(ENTER);
        sb.append("<script>").append(ENTER);
        sb.append(TAB);
        sb.append("$(\"#myButton\").click(function(){").append(ENTER);
        sb.append(TAB2);
        sb.append("$(\"#myForm\").ajaxSubmit({").append(ENTER);
        sb.append(TAB3);
        sb.append("success: function (data) {").append(ENTER);
        sb.append(TAB4);
        sb.append("if (data.resCode == 1 || data.resCode == 2){").append(ENTER);
        sb.append(TAB5);
        sb.append("$(\"#msgDiv\").text(data.resMsg);").append(ENTER);
        sb.append(TAB4);
        sb.append("}").append(ENTER);
        sb.append(TAB3);
        sb.append("},").append(ENTER);
        sb.append(TAB3);
        sb.append("error: function () {").append(ENTER);
        sb.append(TAB4);
        sb.append("$(\"#msgDiv\").text(\"系统出现错误，请联系管理员\");").append(ENTER);
        sb.append(TAB3);
        sb.append("}").append(ENTER);
        sb.append(TAB2);
        sb.append("});").append(ENTER);
        sb.append(TAB);
        sb.append("});").append(ENTER);
        sb.append("document.body.style.backgroundColor = '#ECF0F5';").append(ENTER);
        sb.append("</script>").append(ENTER);


        String companyArr[] = packageName.split("\\.");
        int len = companyArr.length;
        String company = companyArr[len-1];
        String path = RESOURCE_PATH + "views\\" + company +"\\"+ objectName + "\\add.html";
        FileUtils.save(path, sb.toString());
    }

    /**
     * 创建list页面
     * @param table
     * @throws Exception
     */
    public void createPageList(String table, String packageName) throws Exception
    {
        String tableConstantName = getTableConstantName(table);

        String className = getClassName(tableConstantName);//获取类名
        //通过 org.apache.commons.lang3.StringUtils的uncapitalize方法把类名第一个字母转换成小写
        String objectName = StringUtils.uncapitalize(className);
        List<Map<String, Object>> cols = this.getCols(table);

        StringBuilder sb = new StringBuilder();

        sb.append("<% layout('/views/layouts/default.html', {title: '"+className+" List', libs: ['validate']}){ %>").append(ENTER);
        //这个就标注一下，这个taglib.jsp文件是JSTL的EL表达式，Spring 标签，自定义标签，等的文件。
        sb.append("<section class=\"content-header\">").append(ENTER);

        sb.append(TAB).append("<h1>"+objectName+"&nbsp;").append(ENTER);
        sb.append(TAB2).append("<a href=\"/"+objectName+"/listPage\"><button class=\"btn btn-xs jfedit btn-default\">初始化</button></a>&nbsp;").append(ENTER);
        sb.append(TAB2).append("<a href=\"/"+objectName+"/addPage\"><button class=\"btn btn-xs jfedit btn-primary\">新增</button></a>").append(ENTER);
        sb.append(TAB).append("</h1>").append(ENTER);
        sb.append(TAB);
        sb.append("<ol class=\"breadcrumb\">").append(ENTER);

        sb.append(TAB2).append("<li>").append(ENTER);

        sb.append(TAB4).append("<input id=\"id\" name=\"id\" type=\"text\" style=\"width:150px;height:32px;\" placeholder=\"自定义查询,默认ID\" value=\"\"/>").append(ENTER);
        sb.append(TAB4).append("<input id=\"select_button\" class=\"btn btn-sm btn-info\" type=\"submit\" value=\"查询\"/>").append(ENTER);

        sb.append(TAB2).append("</li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;").append(ENTER);

        sb.append(TAB);
        sb.append("</ol>").append(ENTER);
        sb.append("</section>").append(ENTER);
        sb.append(ENTER);
        sb.append("<!-- Main content -->").append(ENTER);
        sb.append("<section class=\"content\">").append(ENTER);
        sb.append(TAB);
        sb.append("<div class=\"row\">").append(ENTER);
        sb.append(TAB).append(TAB);
        sb.append("<div class=\"col-xs-12\">").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB);
        sb.append("<div class=\"box\">").append(ENTER);

        sb.append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("<div class=\"box-body\">").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("<table id=\"example\" class=\"table table-bordered table-hover\" style=\"width:100%\">").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("<thead>").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("<tr>").append(ENTER);

        for(Map<String, Object> col : cols)
        {
            String propertyDBName = col.get(REMARKS).toString();
            String propertyName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, propertyDBName);


            sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
            sb.append("<th>" + propertyName + "</th>").append(ENTER);
        }
        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("<th>操作</th>").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("</tr>").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("</thead>").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("<tbody></tbody>").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("<tfoot>").append(ENTER);

        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);

        sb.append("<tr>").append(ENTER);

        for(Map<String, Object> col : cols)
        {
            String propertyDBName = col.get(REMARKS).toString();
            String propertyName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, propertyDBName);

            sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
            sb.append("<th>" + propertyName + "</th>").append(ENTER);
        }
        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("<th>操作</th>").append(ENTER);

        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("</tr>").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("</tfoot>").append(ENTER);

        sb.append(TAB).append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("</table>").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("</div>").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB);
        sb.append("</div>").append(ENTER);
        sb.append(TAB).append(TAB);
        sb.append("</div>").append(ENTER);
        sb.append(TAB);
        sb.append("</div>").append(ENTER);

        sb.append("</section>").append(ENTER);
        sb.append("<% } %>").append(ENTER).append(ENTER);

        sb.append("<script>").append(ENTER);
        sb.append("$(function() {").append(ENTER);
        sb.append(TAB).append("//重要修改 表格内容的自定义，需要根据业务定制").append(ENTER);
        sb.append(TAB).append("var table = $(\"#example\").dataTable({").append(ENTER);
        sb.append(TAB2).append("<!--lengthMenu: [10,20,50], //如果有修改不生效，请设置bStateSave=false-->").append(ENTER);
        sb.append(TAB2).append("order: [[0, \"desc\" ]],    //默认第一列 倒序").append(ENTER);
        sb.append(TAB2).append("autoWidth: false,  //禁用自动调整列宽").append(ENTER);
        sb.append(TAB2).append("stripeClasses: [\"odd\", \"even\"],  //为奇偶行加上样式，兼容不支持CSS伪类的场合").append(ENTER);
        sb.append(TAB2).append("processing: true,  //隐藏加载提示,自行处理").append(ENTER);
        sb.append(TAB2).append("serverSide: true,  //启用服务器端分页").append(ENTER);
        sb.append(TAB2).append("searching: false,  //禁用原生搜索").append(ENTER);
        sb.append(TAB2).append("orderMulti: true,  //启用多列排序").append(ENTER);
        sb.append(TAB2).append("ordering:true,//使用排序").append(ENTER);
        sb.append(TAB2).append("bStateSave:false,//记录cookie").append(ENTER);
        sb.append(TAB2).append("renderer: \"bootstrap\",  //渲染样式：Bootstrap和jquery-ui").append(ENTER);
        sb.append(TAB2).append("pagingType: \"simple_numbers\",  //分页样式：simple,simple_numbers,full,full_numbers").append(ENTER);
        sb.append(ENTER);

        sb.append(TAB2).append("ajax: function (data, callback, settings) {").append(ENTER);
        sb.append(TAB3).append("//排序字段数组").append(ENTER);

        String orderKeyArr = "[";
        for(int i = 0; i<cols.size();i++)
        {
            Map<String, Object> col = cols.get(i);
            String propertyDBName = col.get(NAME).toString();
            String propertyName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, propertyDBName);

            //最后一个字段
            if(i==cols.size()-1)
            {
                orderKeyArr = orderKeyArr + "'"+propertyName+"']";
                break;
            }
            orderKeyArr = orderKeyArr + "'"+propertyName+"',";
        }
        sb.append(TAB3).append("var orderKeyArr="+orderKeyArr+";").append(ENTER);
        sb.append(ENTER);

        sb.append(TAB3).append("//封装请求参数").append(ENTER);
        sb.append(TAB3).append("var param = {};").append(ENTER);
        sb.append(TAB3).append("param.pageSize= data.length;//页面显示记录条数，在页面显示每页显示多少项的时候").append(ENTER);
        sb.append(TAB3).append("param.pageNum = (data.start / data.length);//当前页码").append(ENTER);
        sb.append(TAB3).append("//自定义的参数").append(ENTER);
        sb.append(TAB3).append("<!--param.type=$(\"select[name='type']\").val();//获取要筛选的类别-->").append(ENTER);
        sb.append(TAB3).append("param.id=$(\"input[name='id']\").val();//获取要筛选的名字").append(ENTER);
        sb.append(TAB3).append("//获取排序的参数").append(ENTER);
        sb.append(TAB3).append("var column = data.order[0].column;").append(ENTER);
        sb.append(TAB3).append("param.orderField= orderKeyArr[column];").append(ENTER);
        sb.append(TAB3).append("param.ascStr= data.order[0].dir;").append(ENTER);
        sb.append(ENTER);
        sb.append(TAB3).append("//ajax请求数据方法").append(ENTER);
        sb.append(TAB3).append("$.ajax({").append(ENTER);
        sb.append(TAB4).append("type: \"GET\",").append(ENTER);
        sb.append(TAB4).append("url: \"/"+objectName+"/list\",//url请求的地址").append(ENTER);
        sb.append(TAB4).append("cache: false,  //禁用缓存").append(ENTER);
        sb.append(TAB4).append("data: param,  //传入组装的参数").append(ENTER);
        sb.append(TAB4).append("dataType: \"json\",").append(ENTER);
        sb.append(TAB4).append("success: function (result) {").append(ENTER);
        sb.append(TAB5).append("//封装返回数据重要").append(ENTER);
        sb.append(TAB5).append("var returnData = {};").append(ENTER);
        sb.append(TAB5).append("//这里直接自行返回了draw计数器,应该由后台返回").append(ENTER);
        sb.append(TAB5).append("<!--returnData.draw = data.draw;-->").append(ENTER);
        sb.append(TAB5).append("//返回数据全部记录").append(ENTER);
        sb.append(TAB5).append("returnData.recordsTotal = result.total;").append(ENTER);
        sb.append(TAB5).append("//后台不实现过滤功能，每次查询均视作全部结果").append(ENTER);
        sb.append(TAB5).append("returnData.recordsFiltered = result.total;").append(ENTER);
        sb.append(TAB5).append("//返回的数据列表").append(ENTER);
        sb.append(TAB5).append("returnData.data = result.records;").append(ENTER);
        sb.append(ENTER);
        sb.append(TAB5).append("//调用DataTables提供的callback方法，代表数据已封装完成并传回DataTables进行渲染").append(ENTER);
        sb.append(TAB5).append("//此时的数据需确保正确无误，异常判断应在执行此回调前自行处理完毕").append(ENTER);
        sb.append(TAB5).append("callback(returnData);").append(ENTER);

        sb.append(TAB4).append("}").append(ENTER);
        sb.append(TAB3).append("});").append(ENTER);
        sb.append(TAB2).append("},").append(ENTER);
        sb.append(ENTER);

        sb.append(TAB2).append("//列表表头字段").append(ENTER);
        sb.append(TAB2).append("\"columns\": [").append(ENTER);
        for(int i = 0; i<cols.size();i++)
        {
            Map<String, Object> col = cols.get(i);
            String propertyDBName = col.get(NAME).toString();
            String propertyName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, propertyDBName);
            sb.append(TAB3).append("{ \"data\": \""+propertyName+"\" },").append(ENTER);

            if(i == cols.size()-1)
            {
                sb.append(TAB3).append("{ \"data\": \""+propertyName+"\" ,\"width\":\"100px\"}").append(ENTER);
            }
        }
        sb.append(TAB2).append("],").append(ENTER);

        sb.append(TAB2).append("\"aoColumnDefs\":[").append(ENTER);
        sb.append(TAB2).append("{//倒数第一列").append(ENTER);
        sb.append(TAB3).append("\"targets\":-1,").append(ENTER);
        sb.append(TAB3).append("\"bSortable\": false,").append(ENTER);
        sb.append(TAB3).append("render: function(data, type, row) {").append(ENTER);
        sb.append(TAB4);
        sb.append("var html ='<a href=\"/"+objectName+"/editPage?id='+row.id+'\"><button class=\"btn btn-xs jfedit btn-info\" value=\"'+row.id+'\">编辑</button></a>&nbsp;&nbsp;&nbsp;&nbsp;'").append(ENTER);
        sb.append(TAB4);
        sb.append("+'<button onclick=\"delFun('+row.id+')\" id=\"delButton\" class=\"btn btn-xs btn-danger jfdelete\">删除</button>';").append(ENTER);
        sb.append(TAB4).append("return html;").append(ENTER);
        sb.append(TAB3).append("}").append(ENTER);
        sb.append(TAB2).append("}]").append(ENTER);

        sb.append(TAB).append("}).api();").append(ENTER);
        sb.append(TAB).append("//此处需调用api()方法,否则返回的是JQuery对象而不是DataTables的API对象").append(ENTER);
        sb.append(ENTER);


        sb.append(TAB).append("//查询按钮").append(ENTER);
        sb.append(TAB).append("$(\"#select_button\").click(function(){").append(ENTER);
        sb.append(TAB2).append("table.ajax.reload();").append(ENTER);

        sb.append(TAB).append("});").append(ENTER);
        sb.append("});").append(ENTER);
        sb.append(ENTER).append(ENTER);





        sb.append("function delFun(id){").append(ENTER);
        sb.append(TAB);
        sb.append("if(confirm(\"确定删除嘛？\")){").append(ENTER);
        sb.append(TAB).append(TAB);
        sb.append("$.ajax({").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB);
        sb.append("url:\"/" + objectName + "/delete?id=\" + id,").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB);
        sb.append("success:function(data){").append(ENTER);
//        sb.append(TAB).append(TAB).append(TAB).append(TAB);
//        sb.append("alert(data.resMsg);").append(ENTER);
        sb.append(TAB).append(TAB).append(TAB).append(TAB);
        sb.append("window.location.href=\"/" + objectName + "/listPage\";").append(ENTER);

        sb.append(TAB).append(TAB).append(TAB);
        sb.append("}").append(ENTER);
        sb.append(TAB).append(TAB);
        sb.append("});").append(ENTER);
        sb.append(TAB);
        sb.append("};").append(ENTER);
        sb.append("}").append(ENTER);
        sb.append("</script>").append(ENTER);

        String companyArr[] = packageName.split("\\.");
        int len = companyArr.length;
        String company = companyArr[len-1];
        String path = RESOURCE_PATH + "views\\" + company +"\\"+ objectName + "\\list.html";
        FileUtils.save(path, sb.toString());
    }


    /***
     * 创建表的类定义常量
     * @param tables
     */
    public void createTableClass(List<String> tables, String packageName)
    {
        StringBuilder sb = new StringBuilder();
        sb.append("package " + packageName + ".domain;");
        sb.append(ENTER);
        sb.append(ENTER);
        sb.append("/**\n * @Created：" + NOW_DATE + "\n * @Author " + AUTHOR + "\n");
        sb.append(" * @Version:").append(Version).append(ENTER);
        sb.append(" * @Email:").append(myEmail).append("\n*/");
        sb.append(ENTER);
        sb.append("public interface Table {");
        sb.append(ENTER);
        for (String table : tables)
        {
            sb.append(TAB);
            sb.append("String " + getTableConstantName(table) + " = \"" + table.toUpperCase() + "\";");
            sb.append(ENTER);
        }
        sb.append(ENTER);
        sb.append("}");
        sb.append(ENTER);
        FileUtils.save(CODE_PATH + packageName.replaceAll("\\.", "/") + "/domain/Table.java", sb.toString());
    }

    /***
     * 获取数据库表名
     * @return
     * @throws Exception
     */
    public List<String> getTables() throws Exception
    {
        List<Object> params = new ArrayList<Object>();
        System.out.println("===========" + JDBC_URL);
        //params.add(JDBC_URL);
        String dbname = JDBC_URL;
        params.add(dbname);

        ResultSet rs = DBHelperUtils.query("select table_name from information_schema.tables where table_schema = ? order by table_name", params);
        List<String> tables = new ArrayList<String>();
        while (rs.next())
        {
            tables.add(rs.getString(1));
        }
        return tables;
    }

    /***
     * 列名 类型 => 说明
     * TABLE_CAT String => 表 catalog
     * TABLE_SCHEM String => 表 schema
     * TABLE_NAME String => 表名
     * TABLE_TYPE String => 表类型
     * REMARKS String => 表注释
     * 获取表的列
     * @param table
     * @return
     * @throws Exception
     */
    private static List<Map<String, Object>> getCols(String table) throws Exception
    {
        List<Map<String, Object>> cols = new ArrayList<Map<String, Object>>();
        ResultSetMetaData md = DBHelperUtils.query("select * from " + table + " where 1 = 2", null).getMetaData();
        ResultSet rs = DBHelperUtils.query("select COLUMN_NAME,column_comment from INFORMATION_SCHEMA.Columns where table_name='"+table+"' and table_schema='"+DB_NAME+"'", null);

        for (int i = 1; i <= md.getColumnCount(); i++)
        {
            Map<String, Object> col = new HashMap<String, Object>();
            cols.add(col);
            col.put(NAME, md.getColumnName(i));
            col.put(CLASS, md.getColumnClassName(i));
            col.put(SIZE, md.getColumnDisplaySize(i));
            col.put(REMARKS, md.getColumnName(i));

            rs.next();
            String remarks = rs.getString("column_comment");
            if(remarks != null && !"".equals(remarks))
            {
                col.put(REMARKS, remarks);
            }

		/*	System.out.println("1"+ md.getCatalogName(i));
			System.out.println("2"+ md.getColumnClassName(i));
			System.out.println("3"+ md.getColumnDisplaySize(i));
			System.out.println("4"+ md.getColumnType(i));
			System.out.println("5"+ md.getSchemaName(i));
			System.out.println("6"+ md.getPrecision(i));
			System.out.println("7"+ md.getScale(i));*/

            String _type = null;
            String type = md.getColumnTypeName(i);
            if (type.equals("INT"))
            {
                _type = "INTEGER";
            } else if (type.equals("DATETIME"))
            {
                _type = "TIMESTAMP";
            } else
            {
                _type = type;
            }
            col.put(TYPE, _type);
        }
        return cols;
    }


    /**
     * 获取所有表
     *
     * @param conn
     * @throws SQLException
     */
    public static List<Map<String, Object>> getAllTable() throws SQLException
    {
        /**
         * 定义一个Lis
         */
        List<Map<String, Object>> cols = new ArrayList<Map<String, Object>>();
        Connection conn = DBHelperUtils.getInstance().getConnection();
        DatabaseMetaData metaData = conn.getMetaData();

        //这个是获取所有表.
        ResultSet rs = metaData.getTables(null, "%", "%", new String[]{"TABLE"});

        while (rs.next())
        {
            String tableName = rs.getString("TABLE_NAME");////这个是获取表名

            if (tableName != null)
            {
                Map<String, Object> col = new HashMap<String, Object>();
                // rs =getConnection.getMetaData().getColumns(null, getXMLConfig.getSchema(),tableName.toUpperCase(), "%");
                //其他数据库不需要这个方法的，直接传null，这个是oracle和db2这么用

                ResultSet rs1 = metaData.getColumns(null, "%", tableName, "%");

                while (rs1.next())
                {
                    String COLUMN_NAME = rs1.getString("COLUMN_NAME");
                    String REMARKS = rs1.getString("REMARKS");
                    //先判断备注是否为空,不为空就取表的字段的注释说明，否则的话就去字段列名
                    if (REMARKS == null || REMARKS == "")
                    {
                        col.put(COLUMN_NAME, COLUMN_NAME);
                    } else
                    {
                        col.put(REMARKS, REMARKS);
                    }
                    cols.add(col);
                }
            }
        }
        return cols;
    }

    /***
     * 获取列的备注
     * @param table
     * @return
     * @throws SQLException
     */
    public static List<Map<String, Object>> getTableRemarks(String table) throws SQLException
    {

        List<Map<String, Object>> cols = new ArrayList<Map<String, Object>>();

        Connection conn = DBHelperUtils.getInstance().getConnection();
        DatabaseMetaData metaData = conn.getMetaData();

        ResultSet rs = metaData.getTables(null, "%", "%", new String[]{"TABLE"});

        while (rs.next())
        {

            String tableName = rs.getString("TABLE_NAME");
            //传进来的表名和查询出来的表名作对比，并且是忽略大小写
            if (tableName != null)
            {
                if (table.equalsIgnoreCase(tableName))
                {
                    Map<String, Object> col = new HashMap<String, Object>();
                    //Map<String, Object> col = new HashTable<String, Object>();
                    ResultSet rs1 = metaData.getColumns(null, "%", tableName, "%");
                    while (rs1.next())
                    {
                        String COLUMN_NAME = rs1.getString("COLUMN_NAME");
                        String REMARKS = rs1.getString("REMARKS");

                        //先判断备注是否为空,不为空就取表的字段的注释说明，否则的话就去字段列名

                        if (REMARKS == null || REMARKS == "")
                        {
                            col.put(COLUMN_NAME, COLUMN_NAME);
                        } else
                        {
                            col.put(REMARKS, REMARKS);
                        }
                        //去掉重复的数据
                        col = removeRepeatData();
                        cols.add(col);
                    }
                    break;
                }
            }
        }
        return cols;
    }

    /***
     * 去掉重复的数据
     * @return
     */
    private static Map<String, Object> removeRepeatData()
    {
        Map<String, Object> col = new HashMap<String, Object>();
        Set<String> keySet = col.keySet();
        for (String str : keySet)
        {
            col.put(str, str);
        }
        return col;
    }


    /***
     * 获取表的常量名，一般是在数据库建表的时候，写的注释..
     * @param table
     * @return
     */
    private String getTableConstantName(String table)
    {
        String tableConstantName = table.toUpperCase();
        for (String item : IGNORE_TABLE_PREFIX)
        {
            tableConstantName = tableConstantName.replaceAll("^" + item.toUpperCase(), "");
        }
        return tableConstantName;
    }

    /***
     * 获取类的名
     * @param name
     * @return
     */
    private String getClassName(String name)
    {
        String[] names = name.split("_");
        StringBuilder sb = new StringBuilder();
        for (String n : names)
        {
            if (n.length() == 0)
            {
                sb.append("_");
            } else
            {
                sb.append(n.substring(0, 1).toUpperCase());
                if (n.length() > 1)
                {
                    sb.append(n.substring(1).toLowerCase());
                }
            }
        }
        return sb.toString();
    }

    /**
     * 获取字段名
     *
     * @param name
     * @return
     */
    private String getFieldName(String name)
    {
        String _name = getClassName(name);
        return _name.substring(0, 1).toLowerCase() + _name.substring(1);
    }


    /**
     * 转换成泛型Map
     *
     * @param limit
     * @param rs
     * @return
     * @throws SQLException
     */
    public static List<Map> toListMap(int limit, ResultSet rs) throws SQLException
    {
        ResultSetMetaData rsmd = rs.getMetaData();
        int count = 0;
        List list = new ArrayList();
        while (rs.next())
        {
            Map row = new HashMap();
            for (int i = 1; i <= rsmd.getColumnCount(); i++)
            {
                row.put(rsmd.getColumnName(i), rs.getObject(i));
            }
            list.add(row);
            count++;
            if (count >= limit)
            {
                break;
            }
        }
        return list;
    }


    /***
     * 获取查询list
     * @param conn
     * @param sql
     * @param limit
     * @return
     * @throws SQLException
     */
    public static List<Map> queryForList(Connection conn, String sql, int limit) throws SQLException
    {
        PreparedStatement ps = conn.prepareStatement(sql.trim());
        ps.setMaxRows(limit);
        ps.setFetchDirection(1000);
        ResultSet rs = ps.executeQuery();
        return toListMap(limit, rs);
    }

    /***
     * 获取查询list
     * @param conn
     * @param sql
     * @param limit
     * @return
     * @throws SQLException
     */
    public static List<Map> queryForList(String sql, int limit) throws SQLException
    {
        Connection conn = DBHelperUtils.getConnection();
        return queryForList(conn, sql, limit);
    }


    public static void main(String[] args) throws Exception
    {
        String sql = "select * from SYS_MENU ";
        //List<Map> queryForList = queryForList(sql, 1000);
		/*for(Map m:queryForList){
			System.out.println("======"+m);
		}*/

        String tableName = "SYS_MENU";//表名

        List<Map<String, Object>> tableRemarks = getTableRemarks(tableName);
        int i = 0;
        for (Map<String, Object> col : getTableRemarks(tableName))
        {
            Set<String> keySet = col.keySet();
            for (Object str : keySet)
            {
                System.out.println(str);
            }
        }

        //new CodeGenerator().createJspView("sup_email");
    }

}
